﻿using System.Collections.Generic;
using System;
using System.Linq;
using System.ComponentModel;

namespace CardGamesLibrary.Cards.Decks
{
    /// <summary>
    /// For most games, the cards are assembled into a deck, and their order is randomized by shuffling.
    /// A complete set of cards is called a pack or deck.
    /// </summary>
    public abstract class Deck<TCard> : List<TCard>, ICardSet<TCard> 
        where TCard : Card
    {
        // this randomizer should be in the concrete deck as the grab random card method
        readonly Random _r;

        protected Deck() : base()
        {
            _r = new Random();
            Reset();

        }

       
        public TCard GrabRandomCard()
        {
            var card =  this.Skip(_r.Next(0, Count)).First();
            Remove(card);
            return card;
        }


        /// <summary>
        /// Inistanciates all the cards of this deck.
        /// </summary>
        protected abstract void InitAllCards();

        /// <summary>
        /// Randomized the card order for all the cards of this deck.
        /// </summary>
        protected void Shuffle()
        {
            for (var i = 0; i < Count; i++)
            {
                SwapCards(i, _r.Next(Count));
            }
        }

        public void Reset()
        {
            Clear();
            InitAllCards();
            Shuffle();
         
        }

        protected void SwapCards(int sourceIndex, int targetIndex)
        {
          
            
            var item = base[sourceIndex];
            Remove(item);
            Insert(targetIndex,item);
        }




        #region INotifyPropertyChanged Members

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = PropertyChanged;

            if (handler != null)
                handler(this, e);
        }
        public void NotifyPropertyChanged(string propertyName)
        {
            NotifyPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}